package com.example.mediarecorderdemo;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.media.Image;
import android.media.ImageReader;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;

import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.example.mediarecorderdemo.databinding.FragmentMyCameraBinding;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;

public class MyCameraFragment extends Fragment {

    private FragmentMyCameraBinding mMyCameraBinding;
    //6.0开始
    private CameraManager mCameraManager;
    private Handler childHandler, mainHandler;
    private CameraDevice mCamera;
    private CaptureRequest.Builder mPreviewBuilder;
    private CameraCaptureSession mSession;
    private ImageReader mImageReader;
    // 创建拍照需要的CaptureRequest.Builder
    private CaptureRequest.Builder captureRequestBuilder;
    private SurfaceHolder mHolder;
    private CameraDevice.StateCallback mCameraDeviceStateCallback;
    private CameraCaptureSession.StateCallback mSessionStateCallback;
    private CameraCaptureSession.CaptureCallback mCaptureCallback;

    public MyCameraFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        mMyCameraBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_my_camera, container, false);
        mMyCameraBinding.setLifecycleOwner(requireActivity());
        initHandler();
        return mMyCameraBinding.getRoot();
    }

    private void initHandler() {
        //很多过程都变成了异步的了，所以这里需要一个子线程的looper
        HandlerThread handlerThread = new HandlerThread("Camera2");
        handlerThread.start();
        childHandler = new Handler(handlerThread.getLooper());
        mainHandler = new Handler(requireActivity().getMainLooper());
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        initCameraManager();
        setImageSize();
        initCameraDeviceStateCallback();
        initCaptureSessionDeviceStateCallback();
        initCaptureCallback();
        mMyCameraBinding.takePhoto.setOnClickListener(view -> {
            CaptureRequest build = captureRequestBuilder.build();
            try {
                mSession.capture(build, null, null);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        });
        mMyCameraBinding.btnJump.setOnClickListener(view -> {
            NavController navController = Navigation.findNavController(view);
            navController.navigate(R.id.action_myCameraFragment_to_recordFragment);
        });
    }

    private void initCaptureCallback() {
        mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                super.onCaptureCompleted(session, request, result);
            }
        };
    }

    private void initCaptureSessionDeviceStateCallback() {
        mSessionStateCallback = new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                mSession = cameraCaptureSession;
                try {
                    captureRequestBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                    // 将imageReader的surface作为CaptureRequest.Builder的目标
                    captureRequestBuilder.addTarget(mImageReader.getSurface());
                    //关闭自动对焦
                    captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
                    captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
                    //设置拍摄图像时相机设备是否使用光学防抖（OIS）。
                    captureRequestBuilder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE, CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON);
                    //曝光补偿//
                    captureRequestBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);
                    updatePreview(cameraCaptureSession);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {

            }
        };
    }

    private void updatePreview(CameraCaptureSession cameraCaptureSession) {
        try {
            cameraCaptureSession.setRepeatingRequest(mPreviewBuilder.build(), mCaptureCallback, childHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void initCameraDeviceStateCallback() {
        mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
            @Override
            public void onOpened(@NonNull CameraDevice cameraDevice) {
                mCamera = cameraDevice;
                startPreview(mCamera);
            }

            @Override
            public void onDisconnected(@NonNull CameraDevice cameraDevice) {
                if (mCamera != null) {
                    mCamera.close();
                    mCamera = null;
                }
            }

            @Override
            public void onError(@NonNull CameraDevice cameraDevice, int i) {
                Log.e("TAG", "onError: ");
            }
        };
    }

    private void startPreview(CameraDevice camera) {
        try {
            mPreviewBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            mPreviewBuilder.addTarget(mHolder.getSurface());
            mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
            mPreviewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
            //设置拍摄图像时相机设备是否使用光学防抖（OIS）。
            mPreviewBuilder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE, CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON);
            //设置自动对焦模式
            mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                    CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            //设置自动曝光模式
            mPreviewBuilder.set(CaptureRequest.CONTROL_AE_MODE,
                    CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

            //创建Session
            mCamera.createCaptureSession(Arrays.asList(mHolder.getSurface(), mImageReader.getSurface()), mSessionStateCallback, childHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void setImageSize() {
        mImageReader = ImageReader.newInstance(1920, 1080, ImageFormat.JPEG, 2);
        mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader imageReader) {
                Image image = imageReader.acquireNextImage();
                ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                byte[] bytes = new byte[buffer.remaining()];
                //使用IO流将照片写入指定文件
                File file = new File(requireActivity().getExternalFilesDir(""), "my.jpg");
                buffer.get(bytes);
                try {
                    FileOutputStream outputStream = new FileOutputStream(file);
                    outputStream.write(bytes);
                    Toast.makeText(requireContext(), "拍照成功,路径为" + file.getPath(), Toast.LENGTH_SHORT).show();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    //释放资源
                    image.close();
                }
            }
        }, mainHandler);
    }

    private void initCameraManager() {
        mCameraManager = (CameraManager) requireActivity().getSystemService(Context.CAMERA_SERVICE);
        mHolder = mMyCameraBinding.textureView.getHolder();
        mHolder.setKeepScreenOn(true);
        mHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
                try {
                    String[] cameraIdList = mCameraManager.getCameraIdList();
                    //打开相机
                    if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                        return;
                    }
                    mCameraManager.openCamera(cameraIdList[0], mCameraDeviceStateCallback, mainHandler);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {
            }

            @Override
            public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
                if (mCamera != null) {
                    mCamera.close();
                    mCamera = null;
                }
            }
        });
    }


}